﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
namespace Dk
{
    /// <summary>
    /// 三种监听事件方式 普通事件 ， 一次性事件， 场景切换移除事件
    /// </summary>
    public class BaseEventManager : BaseManager<BaseEventManager>,IEventManager
    {

        protected Dictionary<string, List<Listener>> listeners = new Dictionary<string, List<Listener>>();
        protected HashSet<Listener> oneceListener = new HashSet<Listener>();
        //挂载在GameObject上的事件 需要判断其挂载物是否还存在 否则会报错
        protected HashSet<Listener> objListener = new HashSet<Listener>();
        //跨场景事件
        protected HashSet<Listener> crossScene = new HashSet<Listener>();



        protected override void Init()
        {

        }

        protected override void Start()
        {

        }



        public void AddListener(string str, Listener listener, EventAddType addType = EventAddType.Normal)
        {
            if (!listeners.ContainsKey(str)) listeners.Add(str, new List<Listener>());
            if (!listeners[str].Contains(listener)) listeners[str].Add(listener);
            if (listener.obj != null) if (!objListener.Contains(listener)) objListener.Add(listener);
            switch (addType)
            {
                case EventAddType.Normal:
                    break;
                case EventAddType.Onece:
                    if (!oneceListener.Contains(listener)) oneceListener.Add(listener);
                    break;
                case EventAddType.OnObject:
                    if (!objListener.Contains(listener)) objListener.Add(listener);
                    break;
                case EventAddType.CrossScene:
                    if (!oneceListener.Contains(listener)) oneceListener.Add(listener);
                    break;
            }

        }

        public void Notify(string str, EventMsg msg = null)
        {
            if (!listeners.ContainsKey(str)) { Debug.LogWarning("不存在事件" + str); return; }

            List<Listener> RemoveList = new List<Listener>();

            foreach (var i in listeners[str])
            {
                if (objListener.Contains(i) && i.obj == null)
                {
                    objListener.Remove(i);
                    RemoveList.Add(i); Debug.LogWarning("目标对象被删除");
                }
                else i.OnNotify(msg);

                if (oneceListener.Contains(i))
                {
                    oneceListener.Remove(i);
                    RemoveList.Add(i);
                }

            }

            if (RemoveList != null || RemoveList.Count > 0)  RemoveList.ForEach((x) => listeners[str].Remove(x)); 

        }

        public void RemoveListener(string str,Listener listener)
        {

        }

        /// <summary>
        /// 注册跨场景事件
        /// </summary>
        /// <param name="str">事件名</param>
        /// <param name="msg">事件信息</param>
        public void RegiteredCrossEvent(string str, EventMsg msg=null)
        {
            Listener listener = new Listener((x) => Instance.Notify(str + "Active", msg), null);
            Instance.AddListener(str + "Ready", listener,EventAddType.CrossScene);
        }

        /// <summary>
        /// 接受跨场景事件
        /// </summary>
        /// <param name="str">跨场景事件名称</param>
        /// <param name="action">响应事件</param>
        public void RegiteredAcceptEvent(string str, Action<EventMsg> action)
        {
            Listener listener = new Listener(action, null);
            Instance.AddListener(str + "Active", listener, EventAddType.Onece);
            Instance.Notify(str + "Ready");

        }


    }
    public class Listener:IListener 
    {
        public delegate void msgaction<in T>(T i) where T : EventMsg;
        protected Action<EventMsg> act;
        public GameObject obj;
        public Listener(GameObject obj=null)
        {
            this.obj = obj;
        }
        
        public Listener(Action<EventMsg>act,GameObject obj=null)
        {
            this.obj = obj;
            this.act = act; 
        }
        public void AddEvent(Action<EventMsg> act)
        {
            this.act += act;
        }
        public void OnNotify(EventMsg msg)
        {
            this.act?.Invoke(msg);
        }
        public void Remove(Action<EventMsg> act)
        {
            this.act -= act;
        }
        public void RemoveAll()
        {
            this.act = null; 
        }

    }

    public class EventMsg
    {
        public string msg; 
    }

    public interface IEventManager {

        void Notify(string str,EventMsg msg=null);
        void AddListener(string str, Listener listener,EventAddType addType=EventAddType.Normal);
        void RemoveListener(string str,Listener listener);
    }
    public interface IListener
    {
        void OnNotify(EventMsg msg);
        void AddEvent(Action<EventMsg> act);
        void Remove(Action<EventMsg> act); 
        void RemoveAll(); 
        
    }
    public enum EventAddType {
        Normal,
        Onece,
        OnObject,
        CrossScene
    }

    public class EventName
    {
        public static string NavgationBarBtnSelect="NavgationBarBtnSelect";
        public static string NavgationBarBtnUnSelect="NavgationBarBtnUnSelect";
        public static string DeatilBtnSelect = "DeatilBtnSelect";
        public static string DeatilBtnUnSelect = "DeatilBtnUnSelect";
        public static string SceneChange = "SceneChange";
        public static string SceneLoad = "SceneLoad";
        public static string NextProcess = "NextProcess";
    }
}

